 /*
 * SPDX-License-Identifier: BSD-3-Clause
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 * Description  : udk usrnl interface
 */

#ifndef UDK_USRNL_H
#define UDK_USRNL_H

#ifndef __KERNEL__
#include <stdint.h>
#include <stdbool.h>

/* *
 * @file udk_usrnl.h
 * @brief Part1: UDK netlink interface definition for OVS/VBS/ISN.
 * 		these three feature ko`s netlink server must implement at
 * 		least driver_msg, mpu_msg and cmdq_msg process.
 * 		UDK netlink packet format as bellow:
 * 		usrnl_msghdr-genlmsghdr-usrnl_nlattr-usrnl_common_msg_hdr or user_defined_hdr
 */

/* *
 * @brief max length usrnl cmd header
 */
#define USRNL_CMD_HDR_LEN_MAX 128

/* *
 * @brief max length usrnl cmd buffer that include header and data
 */
#define USRNL_CMD_BUF_LEN_MAX 2048

/* *
 * @brief get header length usrnl_cmd_buf
 */
#define USRNL_CMD_HDR_LEN(cmd) ((cmd)->hdr_size)

/* *
 * @brief get buffer(header + data) length usrnl_cmd_buf
 */
#define USRNL_CMD_BUF_LEN(cmd) (USRNL_NLA_ALIGN((cmd)->data_size + (cmd)->hdr_size))

/* *
 * @brief get buffer(header + data) address of usrnl_cmd_buf
 */
#define USRNL_CMD_BUF_ADDR(cmd) ((cmd)->hdr_ptr)

/* *
 * @brief get data length usrnl_cmd_buf
 */
#define USRNL_CMD_DATA_LEN(cmd) ((cmd)->data_size)

/* *
 * @brief get data address usrnl_cmd_buf
 */
#define USRNL_CMD_DATA_ADDR(cmd, type) ((type)((void *)(cmd)->data_ptr))

/* *
 * @brief get address of data start plus offset usrnl_cmd_buf
 */
#define USRNL_CMD_DATA_ADDR_OFFSET(cmd, type, offset) ((type)(void *)((cmd)->data_ptr + (offset)))

/* *
 * @brief command buffer api for upper layer lib and app
 */
struct usrnl_cmd_buf {
    void *buf;          /* *< start address of cmd_buf, can not modify after allocated */
    char *data_ptr;     /* *< start address of data */
    char *hdr_ptr;      /* *< start address of header */
    uint16_t data_size; /* *< data length */
    uint16_t hdr_size;  /* *< header length */
};

/* *
 * @brief alloc a cmd_buf from a cmd pool
 * @param usrnl_hdl, owner of cmd pool
 * param size, 0 - use max cmd_buf size USRNL_CMD_BUF_LEN_MAX, other - the size of cmd_buf
 * @retval null-failed, other - the cmd_buf address
 */
struct usrnl_cmd_buf *usrnl_cmd_pool_alloc(void *usrnl_hdl, uint16_t size);

/* *
 * @brief release a cmd_buf from back to cmd pool
 * @param usrnl_hdl, owner of cmd pool
 * param cmd_buf, 0 - the cmd_buf to be released
 * @retval void
 */
void usrnl_cmd_pool_free(void *usrnl_hdl, struct usrnl_cmd_buf *cmd_buf);

/* *
 * @brief create a netlink with kernel using family name
 * @param usrnl_hdl, the return value of usrnl
 * @retval 0-success negative-error_code
 */
int32_t usrnl_create(void **usrnl_hdl, const char *nl_family_name);

/* *
 * @brief destroy a netlink
 * @param usrnl_hdl, the usrnl to be destroyed
 * @retval void
 */
void usrnl_destroy(void *usrnl_hdl);

/* *
 * @brief send a netlink command to kernel and get response
 * @param usrnl_hdl, the usrnl that the netlink belongs to
 * @param cmd, one of usrnl_dev_cmd
 * @param cmd_in, command buffer
 * @param rsp_out, response buffer
 * @retval retval 0-success negative-linux base error code
 */
int32_t usrnl_send_cmd_recv_rsp(void *usrnl_hdl, uint16_t cmd, struct usrnl_cmd_buf *cmd_in,
    struct usrnl_cmd_buf *rsp_out);

/* *
 * @brief send a message to cmdq via kernel netlink and get response
 * @param usrnl_hdl, the usrnl that the netlink belongs to
 * @param cmd, one of usrnl_dev_cmd
 * @param cmd_in, command buffer
 * @param rsp_out, response buffer
 * @retval retval 0-success negative-linux base error code
 */
int32_t usrnl_exec_cmdq_cmd(void *usrnl_hdl, struct usrnl_cmd_buf *cmd_in, struct usrnl_cmd_buf *rsp_out);

/* *
 * @brief send a message to mpu via kernel netlink and get response
 * @param usrnl_hdl, the usrnl that the netlink belongs to
 * @param cmd, one of usrnl_dev_cmd
 * @param cmd_in, command buffer
 * @param rsp_out, response buffer
 * @retval retval 0-success negative-linux base error code
 */
int32_t usrnl_exec_mgmt_msg(void *usrnl_hdl, struct usrnl_cmd_buf *cmd_in, struct usrnl_cmd_buf *rsp_out);

/* *
 * @brief send a message to driver via kernel netlink and get response
 * @param usrnl_hdl, the usrnl that the netlink belongs to
 * @param cmd, one of usrnl_dev_cmd
 * @param cmd_in, command buffer
 * @param rsp_out, response buffer
 * @retval retval 0-success negative-linux base error code
 */
int32_t usrnl_exec_drv_cmd(void *usrnl_hdl, struct usrnl_cmd_buf *cmd_in, struct usrnl_cmd_buf *rsp_out);

/* *
 * @brief send a message to vf via kernel netlink and get response
 * @param usrnl_hdl, the usrnl that the netlink belongs to
 * @param cmd, one of usrnl_dev_cmd
 * @param cmd_in, command buffer
 * @param rsp_out, response buffer
 * @retval retval 0-success negative-linux base error code
 */
int32_t usrnl_exec_vf_cmd(void *usrnl_hdl, struct usrnl_cmd_buf *cmd_in, struct usrnl_cmd_buf *rsp_out);

/* *
 * @brief block netlink and get flush netlink-sockets status during sdi-nanoos hot replace.
 * @param flag, true : block netlink; false : non-block netlink
 * @param usrnl_hdl, the usrnl that the netlink belongs to
 * @retval retval 0-success negative-linux base error code
 */
int32_t netlink_block_and_get_flush_status(bool flag, void *usrnl_hdl);

#endif

/* *
 * @brief cmdq_direct_resp or cmdq_detail_resp
 */
#define USRNL_CMDQ_DIRECT (0)
#define USRNL_CMDQ_DETAIL (1)

#define USRNL_GENL_ATTR_MAX (__USRNL_GENL_ATTR_MAX - 1)

/* *
 * @brief usrnl message cmd and header definitions
 */
enum usrnl_dev_cmd {
    USRNL_DEV_CMD_UNSPEC,
    USRNL_DEV_MPU_CMD_EXECUTE, // to mpu
    USRNL_DEV_VF_CMD_EXECUTE,  // to vf's mailbox
    USRNL_DEV_DRV_CMD_EXECUTE, // to driver's resource init
    USRNL_DEV_CMDQ_CMD_EXECUTE // to ucode via cmdq
};

enum usrnl_genl_attr {
    USRNL_GENL_ATTR_UNSPEC,
    USRNL_GENL_ATTR, /* u32 port number within datapath */
    __USRNL_GENL_ATTR_MAX
};

/* *
 * @brief netlink drver/mpu/cmdq message header definitions
 */
struct usrnl_common_msg_hdr {
    // DW0
    unsigned int cmd     : 16; // user defined command
    unsigned int msg_len : 11; // total message length, maximum (2 << 11) -1
    unsigned int module  : 5;  // module id

    // DW1
    unsigned int src_func_idx : 16; // source function id,for pf2up this is msg_id
    unsigned int rsp_type : 8;      // rsvd2
    unsigned int err_code : 8;      // rsvd1
};

typedef struct usrnl_common_msg_hdr usrnl_drv_msg_hdr_s;
typedef struct usrnl_common_msg_hdr usrnl_mpu_msg_hdr_s;
typedef struct usrnl_common_msg_hdr usrnl_cmdq_msg_hdr_s;

#define USRNL_FILL_DRV_MSG_HDR(hdr, dcmd, len) \
    do {                            \
        (hdr)->cmd = (dcmd);                         \
        (hdr)->msg_len = (len);                         \
    } while (0)

#define USRNL_FILL_MPU_MSG_HDR(hdr, upcmd, len, mod, func_id) \
    do {                            \
        (hdr)->cmd = (upcmd);                                       \
        (hdr)->msg_len = (len);                                     \
        (hdr)->module = (mod);                                      \
        (hdr)->src_func_idx = (func_id);                            \
    } while (0)

#define USRNL_FILL_CMDQ_MSG_HDR(hdr, ccmd, len, mod, func_id) \
    do {                            \
        (hdr)->cmd = (ccmd);                                             \
        (hdr)->msg_len = (len);                                          \
        (hdr)->module = (mod);                                           \
        (hdr)->src_func_idx = (func_id);                                 \
        (hdr)->rsp_type = USRNL_CMDQ_DIRECT;                                 \
    } while (0)

#endif /* UDK_USRNL_H */

